<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>WebRTC 实时视频聊天</title>
    <style>
      body {
        font-family: Arial, sans-serif;
        max-width: 900px;
        margin: 0 auto;
        padding: 20px;
        background-color: #f5f5f5;
      }
      h1 {
        color: #333;
        text-align: center;
      }
      .video-container {
        display: flex;
        flex-wrap: wrap;
        gap: 20px;
        margin-bottom: 20px;
      }
      .video-box {
        flex: 1;
        min-width: 300px;
        background: #fff;
        border-radius: 8px;
        padding: 15px;
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
      }
      video {
        width: 100%;
        background: #000;
        border-radius: 4px;
      }
      .controls {
        display: flex;
        flex-direction: column;
        gap: 10px;
        background: #fff;
        padding: 15px;
        border-radius: 8px;
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
      }
      button {
        padding: 10px 15px;
        background: #4285f4;
        color: white;
        border: none;
        border-radius: 4px;
        cursor: pointer;
        font-size: 16px;
        transition: background 0.3s;
      }
      button:hover {
        background: #3367d6;
      }
      button:disabled {
        background: #cccccc;
        cursor: not-allowed;
      }
      .status {
        margin-top: 10px;
        padding: 10px;
        border-radius: 4px;
        background: #f0f0f0;
      }
    </style>
  </head>
  <body>
    <h1>WebRTC 实时视频聊天</h1>

    <div class="video-container">
      <div class="video-box">
        <h3>本地视频</h3>
        <video id="localVideo" autoplay muted playsinline></video>
      </div>
      <div class="video-box">
        <h3>远程视频</h3>
        <video id="remoteVideo" autoplay playsinline></video>
      </div>
    </div>

    <div class="controls">
      <button id="startButton">开始视频</button>
      <button id="callButton" disabled>发起通话</button>
      <button id="hangupButton" disabled>结束通话</button>
      <div class="status" id="status">状态: 等待开始...</div>
    </div>

    <script>
      // 获取DOM元素
      const localVideo = document.getElementById("localVideo");
      const remoteVideo = document.getElementById("remoteVideo");
      const startButton = document.getElementById("startButton");
      const callButton = document.getElementById("callButton");
      const hangupButton = document.getElementById("hangupButton");
      const statusDiv = document.getElementById("status");

      // WebRTC相关变量
      let localStream;
      let pc1;
      let pc2;
      const offerOptions = {
        offerToReceiveAudio: 1,
        offerToReceiveVideo: 1,
      };

      // 1. 开始本地视频
      startButton.onclick = async () => {
        try {
          statusDiv.textContent = "正在获取本地媒体流...";
          localStream = await navigator.mediaDevices.getUserMedia({
            audio: true,
            video: true,
          });
          localVideo.srcObject = localStream;
          statusDiv.textContent = "本地视频已开启";
          startButton.disabled = true;
          callButton.disabled = false;
        } catch (e) {
          statusDiv.textContent = `获取媒体失败: ${e.toString()}`;
          console.error("获取用户媒体失败:", e);
        }
      };

      // 2. 发起通话
      callButton.onclick = async () => {
        callButton.disabled = true;
        hangupButton.disabled = false;
        statusDiv.textContent = "正在建立连接...";

        try {
          // 创建两个RTCPeerConnection对象模拟两端
          pc1 = new RTCPeerConnection();
          pc2 = new RTCPeerConnection();

          // 添加ICE候选
          pc1.onicecandidate = (event) => {
            if (event.candidate) {
              pc2
                .addIceCandidate(event.candidate)
                .catch((e) => console.error("添加ICE候选失败:", e));
            }
          };

          pc2.onicecandidate = (event) => {
            if (event.candidate) {
              pc1
                .addIceCandidate(event.candidate)
                .catch((e) => console.error("添加ICE候选失败:", e));
            }
          };

          // 当远程流到达时，显示它
          pc2.ontrack = (event) => {
            if (remoteVideo.srcObject !== event.streams[0]) {
              remoteVideo.srcObject = event.streams[0];
              statusDiv.textContent = "已建立连接，正在通话中...";
            }
          };

          // 添加本地流到pc1
          localStream.getTracks().forEach((track) => {
            pc1.addTrack(track, localStream);
          });

          // 创建offer并设置本地描述
          const offer = await pc1.createOffer(offerOptions);
          await pc1.setLocalDescription(offer);
          statusDiv.textContent =
            "pc1 设置本地描述: \n" + offer.sdp.substring(0, 100) + "...";

          // 设置远程描述并创建answer
          await pc2.setRemoteDescription(offer);
          const answer = await pc2.createAnswer();
          await pc2.setLocalDescription(answer);
          statusDiv.textContent +=
            "\npc2 设置本地描述: \n" + answer.sdp.substring(0, 100) + "...";

          // 完成信令
          await pc1.setRemoteDescription(answer);
          statusDiv.textContent = "连接已建立，正在通话中...";
        } catch (e) {
          statusDiv.textContent = `建立连接失败: ${e.toString()}`;
          console.error("建立连接失败:", e);
        }
      };

      // 3. 结束通话
      hangupButton.onclick = () => {
        if (pc1) {
          pc1.close();
          pc1 = null;
        }
        if (pc2) {
          pc2.close();
          pc2 = null;
        }
        remoteVideo.srcObject = null;
        hangupButton.disabled = true;
        callButton.disabled = false;
        statusDiv.textContent = "通话已结束";
      };
    </script>
  </body>
</html>
